<template>
  <div class="chat-window-page">
    <div class="chat-content">
      <div class="chat-list">
        <div class="chat-list-opt">
          <ArrowLeftOutlined class="chat-list-opt-back" @click="goBack" />
        </div>
        <div class="chat-list-my">
          <a-avatar shape="square" :size="64" class="chat-list-my-avatar"> S </a-avatar>
          <div class="chat-list-my-text">SCL</div>
          <EllipsisOutlined class="chat-list-my-opt" />
        </div>
        <div class="chat-list-tab">
          <div
            class="chat-list-tab-item"
            :class="{ active: activeKey === 'chats' }"
            @click="handleChangeTab('chats')"
          >
            <MessageFilled class="chat-list-tab-item-icon" />
          </div>
          <div
            class="chat-list-tab-item"
            :class="{ active: activeKey === 'friends' }"
            @click="handleChangeTab('friends')"
          >
            <UserOutlined class="chat-list-tab-item-icon" />
          </div>
        </div>
        <div class="chat-list-wrap chats-list" v-if="activeKey === 'chats'">
          <div class="chats-list-item-wrap" v-for="i in 20" :key="i">
            <a-avatar shape="square" :size="50" :gap="10"> 测试 </a-avatar>
            <div class="chats-list-item">
              <div class="chats-list-item-info">
                <div class="chats-list-item-info-name">测试</div>
                <div class="chats-list-item-info-time">昨天</div>
              </div>
              <div class="chats-list-item-content">
                <div class="chats-list-item-content-text">
                  你好，测试啊是测试从打发发达打法发的萨芬
                </div>
                <div class="chats-list-item-content-tip">5</div>
              </div>
            </div>
          </div>
        </div>
        <div class="chat-list-wrap friends-list" v-else></div>
      </div>
      <div class="chat-window">
        <div class="chat-window-header">测试</div>
        <div class="chat-window-content" ref="chatWindow">
          <div
            class="chat-window-content-item"
            :class="item.fromId != userStore.userInfo.id ? 'left' : 'right'"
            v-for="(item, i) in chatList"
            :key="i"
          >
            <template v-if="item.fromId != userStore.userInfo.id">
              <a-avatar shape="square" size="large" :gap="5"> 测试{{ item.id }}</a-avatar>
              <div class="chat-window-content-item-bubble" v-html="item.msg"></div>
            </template>
            <template v-else>
              <div class="chat-window-content-item-bubble" v-html="item.msg"></div>
              <a-avatar shape="square" size="large" :gap="5"> 测试{{ item.id }}</a-avatar>
            </template>
          </div>
        </div>
        <div class="chat-window-content-opt">
          <div class="chat-window-content-opt-input">
            <!-- <a-textarea
              :bordered="false"
              style="resize: none"
              v-model:value="sendMsg.msg"
              @pressEnter="handleEnter"
            /> -->
            <QuillEditor content-type="html" v-model:content="sendMsg.msg" />
          </div>
          <div class="chat-window-content-opt-send">
            <a-button @click="websocketsend()">发送</a-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import router from '@/router'
import { useUserStore } from '@/stores'
import { message } from 'ant-design-vue'
const userStore = useUserStore()
const lockReconnect = ref(false)
const reconnectNum = ref(0)
const timeout = ref(20 * 1000)
const timeoutObj = ref(null)
const serverTimeoutObj = ref(null)
const timeoutnum = ref(null)
const sendMsg = ref({
  fromId: userStore.userInfo.id,
  toId: userStore.userInfo.id == '1' ? '2' : '1',
  msg: null
})
const chatList = ref([])

const activeKey = ref('chats')

const chatWindow = ref(null)
const handleChangeTab = (key) => {
  activeKey.value = key
}
const goBack = () => {
  router.back()
}

const handleEnter = (e) => {
  if (!e.shiftKey) {
    e.preventDefault() // 阻止默认换行行为
    websocketsend()
  }
}

onMounted(() => {
  if (!(window.websocket && window.websocket.readyState == 1)) initWebSocket()
})

onUnmounted(() => {
  websocketclose(true)
  window.websocket = null
})

const initWebSocket = () => {
  const wsuri = 'ws://localhost:7001/websocket/' + userStore.userInfo.id
  //建立连接
  let websocket = new WebSocket(wsuri)
  //连接成功
  websocket.onopen = () => websocketonopen()
  //连接错误
  websocket.onerror = (e) => websocketonerror(e)
  //接收信息
  websocket.onmessage = (event) => websocketonmessage(event)
  //连接关闭
  websocket.onclose = () => websocketclose()

  window.websocket = websocket
}

const reconnect = () => {
  //重新连接
  //判断链接状态，true就是链接，false是断开，这里如果是链接状态就不继续执行了，跳出来。
  if (lockReconnect.value) {
    return
  }
  //把链接状态改为true
  lockReconnect.value = true
  //没连接上会一直重连，设置延迟避免请求过多
  timeoutnum.value && clearTimeout(timeoutnum.value)
  timeoutnum.value = setTimeout(function () {
    //初始化新连接
    initWebSocket()
    //把链接状态改为false
    lockReconnect.value = false
  }, 5000)
}

const reset = () => {
  //清除时间
  clearTimeout(timeoutObj.value)
  clearTimeout(serverTimeoutObj.value)
  //重启心跳
  start()
}
const start = () => {
  //开启心跳
  //有延迟时间的就清除掉
  timeoutObj.value && clearTimeout(timeoutObj.value)
  serverTimeoutObj.value && clearTimeout(serverTimeoutObj.value)
  //从新创建计时器
  timeoutObj.value = setTimeout(function () {
    //这里发送一个心跳，后端收到后，返回一个心跳消息
    if (window.websocket.readyState == 1) {
      //如果连接正常发送信息到后台
      websocketsend({ toId: 'server', msg: 'ping' })
    } else {
      //否则重连
      reconnect()
    }
    serverTimeoutObj.value = setTimeout(function () {
      //超时关闭
      window.websocket.close()
    }, timeout.value)
  }, timeout.value)
}
//链接成功时执行的方法
const websocketonopen = () => {
  //连接成功事件
  websocketsend({ toId: 'server', msg: 'heartbeat' })
  //提示成功
  console.log('连接成功', window.websocket)
  //开启心跳
  start()
}
//连接失败事件
const websocketonerror = (e) => {
  //错误
  console.log('WebSocket连接发生错误')
  if (reconnectNum.value++ > 3) {
    return
  }
  //重连
  reconnect()
}
//连接关闭事件
const websocketclose = (flag) => {
  window.websocket.close()
  //提示关闭
  console.log('连接已关闭')
  //重连
  if (!flag) reconnect()
}
//接收服务器推送的信息
const websocketonmessage = (event) => {
  //打印收到服务器的内容
  let messageObj = JSON.parse(event.data)
  if (messageObj.fromId != messageObj.toId) {
    chatList.value.push(messageObj)
    scrollToBottom()
  }
  //收到服务器信息，心跳重置
  reset()
}
const websocketsend = (msgObj) => {
  if (!msgObj) msgObj = sendMsg.value
  if (!msgObj.msg) {
    message.warning('请输入内容')
    sendMsg.value.msg = null
    return
  }
  console.log(JSON.stringify(msgObj))
  //向服务器发送信息
  window.websocket.send(JSON.stringify(msgObj))
  if (msgObj.toId != 'server') {
    chatList.value.push(JSON.parse(JSON.stringify(msgObj)))
    sendMsg.value.msg = null
    scrollToBottom()
  }
}

const scrollToBottom = () => {
  if (chatWindow.value) {
    nextTick(() => {
      chatWindow.value.scrollTop = chatWindow.value.scrollHeight
    })
  }
}
</script>

<style lang="scss" scoped>
.chat-window-page {
  width: 100%;
  height: 100%;
  .chat-content {
    display: flex;
    height: 100%;
    .chat-list {
      width: 15%;
      height: 100%;
      background: rgba(231, 231, 231, 0.5);
      .chat-list-opt {
        width: 100%;
        height: 3%;
        padding: 0 10px;
        display: flex;
        align-items: center;
        .chat-list-opt-back {
          cursor: pointer;
        }
      }
      .chat-list-my {
        width: 100%;
        height: 10%;
        padding: 0 10px;
        display: flex;
        align-items: center;
        .chat-list-my-avatar {
          background: red;
        }
        .chat-list-my-text {
          margin-left: 10px;
          color: #000;
          font-size: 18px;
        }
        .chat-list-my-opt {
          color: #000;
          margin-left: auto;
          font-size: 20px;
          cursor: pointer;
        }
      }
      .chat-list-tab {
        height: 5%;
        width: 100%;
        display: flex;
        border-bottom: 1px solid rgba(0, 0, 0, 0.349);
        .chat-list-tab-item {
          width: 50%;
          height: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          position: relative;
          cursor: pointer;
          .chat-list-tab-item-icon {
            font-size: 20px;
            color: #0000006c;
          }
          &.active {
            .chat-list-tab-item-icon {
              color: rgb(151, 230, 34);
            }
          }
          &:first-child::after {
            content: '';
            width: 1px;
            height: 50%;
            background: rgba(201, 201, 201, 0.534);
            position: absolute;
            right: 0.5px;
          }
        }
      }
      .chat-list-wrap {
        width: 100%;
        height: calc(100% - 18%);
        overflow-y: auto;
        &::-webkit-scrollbar {
          display: none;
        }
      }
      .chats-list {
        .chats-list-item-wrap {
          width: 100%;
          height: 70px;
          padding: 0 10px;
          display: flex;
          justify-content: space-between;
          align-items: center;
          border-bottom: 1px solid #0000001f;
          cursor: pointer;
          &:hover {
            background: rgba(0, 0, 0, 0.06);
          }
          .chats-list-item {
            height: 100%;
            width: calc(100% - 60px);
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            .chats-list-item-info {
              width: 100%;
              height: 50%;
              display: flex;
              justify-content: space-between;
              align-items: center;
              color: #707070;
              .chats-list-item-info-name {
                font-size: 16px;
              }
            }
            .chats-list-item-content {
              width: 100%;
              height: 50%;
              display: flex;
              align-items: center;
              justify-content: space-between;
              .chats-list-item-content-text {
                width: 80%;
                text-overflow: ellipsis;
                white-space: nowrap;
                overflow: hidden;
                color: #979797;
                font-size: 12px;
              }
              .chats-list-item-content-tip {
                width: 18px;
                height: 18px;
                background: #ff0000;
                color: #fff;
                border-radius: 50%;
                text-align: center;
                line-height: 18px;
                font-size: 12px;
              }
            }
          }
        }
      }
    }
    .chat-window {
      width: 85%;
      height: 100%;
      background: rgba(241, 241, 241, 0.6);
      .chat-window-header {
        height: 7%;
        width: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 0 10px;
        font-size: 20px;
        color: #707070;
        border-bottom: 1px solid rgba(0, 0, 0, 0.349);
      }
      .chat-window-content {
        width: 100%;
        height: 78%;
        padding: 10px 20px;
        overflow-y: auto;
        &::-webkit-scrollbar {
          display: none;
        }
        .chat-window-content-item {
          width: 100%;
          min-height: 50px;
          display: flex;
          .chat-window-content-item-bubble {
            position: relative;
            padding: 10px 15px;
            border-radius: 10px;
            margin: 10px 0;
            max-width: 70%;
            line-height: 1.5;
            background-color: #e5e5ea;
            max-width: 100%;
          }
        }
        .left {
          .chat-window-content-item-bubble {
            align-self: flex-start;
            margin-left: 20px;
            &::before {
              content: '';
              position: absolute;
              top: 15px;
              left: -10px;
              width: 0;
              height: 0;
              border: 10px solid transparent;
              border-right-color: #e5e5ea;
              border-left: 0;
              border-top: 0;
              margin-top: -5px;
            }
          }
        }
        .right {
          justify-content: flex-end;
          .chat-window-content-item-bubble {
            background-color: #007aff;
            color: white;
            align-self: flex-end;
            margin-right: 20px;
            &::before {
              content: '';
              position: absolute;
              top: 15px;
              right: -10px;
              width: 0;
              height: 0;
              border: 10px solid transparent;
              border-left-color: #007aff;
              border-right: 0;
              border-top: 0;
              margin-top: -5px;
            }
          }
        }
      }
      .chat-window-content-opt {
        padding: 0 10px;
        width: 100%;
        height: 15%;
        border-top: 1px solid rgba(0, 0, 0, 0.349);
        .chat-window-content-opt-input {
          height: 70%;
          width: 100%;
          :deep(.ql-toolbar.ql-snow) {
            display: none;
          }
          :deep(.ql-container.ql-snow) {
            border: none;
          }
        }
        .chat-window-content-opt-send {
          height: 30%;
          width: 100%;
          display: flex;
          justify-content: flex-end;
        }
      }
    }
  }
}
</style>
